#include "dorgen.h"

#include <algorithm>
#include <QTime>
#include <QDebug>


Dorgen::Dorgen()
{
    /* Generating seed */
    QTime time = QTime::currentTime();
    srand((uint)time.msec());
    qsrand((uint)time.msec());
}

void Dorgen::setSettings(const QString& path)
{
    settingsPath = path;
    QSettings settings(path, QSettings::IniFormat);

    createFolder((settings.contains("Main/Folder") ? settings.value("Main/Folder").toString() : "folder"), (settings.contains("Main/WriteInExists") ? settings.value("Main/WriteInExists").toBool() : false));

    if(!settings.contains("Main/PagesNumber"))
        emit unsetted("Не задано количество генерируемых страниц");

    pages_number = settings.value("Main/PagesNumber").toInt();

    if(settings.contains("Keys/File"))
        formKeys(settings.value("Keys/File").toString(), (settings.contains("Keys/Count") ? settings.value("Keys/Count").toInt() : 0), (settings.contains("Keys/Shuffle") ? settings.value("Keys/Shuffle").toBool() : false) );

    if(settings.contains("Text/Files"))
        formText(settings.value("Text/Files").toStringList());

    if(settings.contains("Template/Directory"))
        formTemplate(settings.value("Template/Directory").toString(), (settings.contains("Template/CopyAll") ? settings.value("Template/CopyAll").toBool() : false));
    else
        emit unsetted("Не задан шаблон для генерации");


    QString str("[php]echo mt_rand(0,1);[/php] [TRANSLIT(и конечно-же)] [php]echo mt_rand(0,1);[/php]");
    macros(str);
    qDebug() << str;
}

void Dorgen::createFolder(const QString &name, bool in_exists)
{
    folder = name;
    QDir dir;

    if(!in_exists)
    {
        int i = 0;
        while(dir.exists(folder))
        {
            folder += QString::number(i);
            i++;
        }
    }
    if(!dir.exists(folder))
        if(!dir.mkdir(folder))
            emit failedOpen(QString("Ошибка создания категории %1").arg(folder));
}

void Dorgen::formKeys(const QString &filePath, int number, bool shuffle)
{
    QFile file(filePath);

    if(!file.open(QIODevice::ReadOnly))
    {
        emit failedOpen(QString("Ошибка открытия файла %1").arg(filePath));
        return;
    }

    QStringList lines;
    QTextStream in(&file);
    QString line = in.readLine();
    while (!line.isNull()) {
        lines << line;
        line = in.readLine();
    }
    number = (number == 0) ? lines.size() : number;

    if(shuffle)
        std::random_shuffle ( lines.begin(), lines.end() );

    for(int i = 0; i<number; i++)
        keys_list << lines[i];
}

void Dorgen::formText(const QStringList &files)
{
    for(int i = 0; i<files.size();i++)
    {
        if(QFile::exists(files[i]))
            text_files << files[i];
    }

    if(text_files.isEmpty())
        emit unsetted("Не задан ни один валидный текстовый файл");
}

void Dorgen::formTemplate(const QString &path, bool all)
{
    if(!QFile::exists(path + QDir::separator() + "template.tpl"))
        emit failedOpen(QString("Не найден файл %1/template.tpl").arg(path));
    if(all)
        copyFolder(path, folder, QStringList("template.tpl"));
}

int Dorgen::randInt(int min, int max)
{
    return qrand() % ((max + 1) - min) + min;
}

void Dorgen::copyFolder(const QString& sourceFolder, const QString& destFolder, const QStringList& filters)
{
    QDir sourceDir(sourceFolder);
    if(!sourceDir.exists())
        return;
    QDir destDir(destFolder);
    if(!destDir.exists())
    {
        QDir dir;
        dir.mkdir(destFolder);
    }
    QStringList files = sourceDir.entryList(QDir::Files);

    for(int i = 0; i< files.count(); i++)
    {
        if(filters.contains(files[i]))
            continue;
        QString srcName = sourceFolder + QDir::separator() + files[i];
        QString destName = destFolder + QDir::separator() + files[i];
        QFile::copy(srcName, destName);
    }
    files.clear();
    files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);

    for(int i = 0; i< files.count(); i++)
    {
        QString srcName = sourceFolder + QDir::separator() + files[i];
        QString destName = destFolder + QDir::separator() + files[i];
        copyFolder(srcName, destName, filters);
    }
}

void Dorgen::macros(QString &source)
{
    int pos = 0;

    /* [RAND-(a,b)] - генерация числа по диапозону */
    QRegExp rand("\\[RAND-\\((\\d+),(\\d+)\\)\\]");
    while ((pos = rand.indexIn(source, pos)) != -1)
    {
        source.replace(pos, rand.matchedLength(), QString::number(randInt(rand.cap(1).toInt(), rand.cap(2).toInt())));
    }   pos = 0;

    /* [TRANSLIT(text)] - транслит заданного текста */
    QRegExp tr("\\[TRANSLIT\\((.+)\\)\\]");
    tr.setMinimal(true);
    while ((pos = tr.indexIn(source, pos)) != -1)
    {
        source.replace(pos, tr.matchedLength(), translit(tr.cap(1)));
    }   pos = 0;

    /* {REPLACEMENT-(regexp)-(replace)}text{/REPLACEMENT} */
    QRegExp replacement("\\{REPLACEMENT-\\(.+\\)-\\(.+\\)\\}.+\\{/REPLACEMENT\\}");
    if(replacement.exactMatch(source))
    {
        qDebug() << replacement.cap(0);
    }

    QRegExp php("\\[php\\](.+)\\[/php\\]");
    php.setMinimal(true);
    while ((pos = php.indexIn(source, pos)) != -1)
    {
        QString result;
        executePhp(php.cap(1), result);
        source.replace(pos, php.matchedLength(), result);
    }   pos = 0;
}


bool Dorgen::executePhp(const QString &code, QString &string)
{
    QStringList arguments;
    arguments << "-r" << code;
    QProcess php;
    php.start("/usr/bin/php", arguments);
    if (!php.waitForStarted())
             return false;
    if (!php.waitForFinished())
             return false;
    string += php.readAll();
    return true;
}

//[FIXME] определение chars
QString Dorgen::translit(const QString &string)
{
    QString str(string.toLower());

    QHash<QChar, QString> chars;
    chars[0x430] = "a"; /*а*/
    chars[0x431] = "b"; /*б*/
    chars[0x432] = "v"; /*в*/
    chars[0x433] = "g"; /*г*/
    chars[0x434] = "d"; /*д*/
    chars[0x435] = "e"; /*е*/
    chars[0x436] = "j";/*ж*/
    chars[0x437] = "z"; /*з*/
    chars[0x438] = "i"; /*и*/
    chars[0x439] = "y"; /*й*/
    chars[0x43A] = "k"; /*к*/
    chars[0x43B] = "l"; /*л*/
    chars[0x43C] = "m"; /*м*/
    chars[0x43D] = "n"; /*н*/
    chars[0x43E] = "o"; /*о*/
    chars[0x43F] = "p"; /*п*/
    chars[0x440] = "r"; /*р*/
    chars[0x441] = "s"; /*с*/
    chars[0x442] = "t"; /*т*/
    chars[0x443] = "u"; /*у*/
    chars[0x444] = "f"; /*ф*/
    chars[0x445] = "h"; /*x*/
    chars[0x446] = "c"; /*ц*/
    chars[0x447] = "ch";/*ч*/
    chars[0x448] = "sh";/*ш*/
    chars[0x449] = "sh";/*щ*/
    chars[0x44A] = "";  /*ъ*/
    chars[0x44B] = "i"; /*ы*/
    chars[0x44C] = "";  /*ь*/
    chars[0x44D] = "e"; /*э*/
    chars[0x44E] = "yu";/*ю*/
    chars[0x44F] = "ya";/*я*/

    QString result;

    foreach( QChar ch, str ) {
        result += ( chars.contains( ch ) ) ? chars[ch] : ch;
    }

    return result;
}
